using Kopernikus.Collections.Generic;
using Kopernikus.Parsing.LR;

namespace Kopernikus.Parsing.Earley
{
    public class LazyEarleyDFA : EarleyDFA
    {
        public LazyEarleyDFA(IGrammar grammar) : base(grammar)
        {
        }

        public override int GetGoto(int state, Symbol s)
        {
            if (state == InvalidState)
            {
                return InvalidState;
            }

            int gotoState;
            if (!TryGetGoto(state, s, out gotoState))
            {
                // TODO: Assert s is non-terminal
                Set<LR0Item> stateSet = StateSets[state];

                Set<LR0Item> kernelSet = AdvanceStateItems(s, stateSet);

                Set<LR0Item> nonKernelSet = GetClosure(kernelSet);
                nonKernelSet.Remove(kernelSet);

                int kernelState = AddStateSet(kernelSet);
                int nonKernelState = AddStateSet(nonKernelSet);

                DefineGoto(state, s, kernelState);
                DefineGoto(kernelState, Symbol.Epsilon, nonKernelState);
            }
            return base.GetGoto(state, s);
        }


        public override int Build()
        {
            int initialState = base.Build();
            DefineGoto(initialState, Symbol.Epsilon, AddStateSet(GetClosure(StateSets[initialState])));
            return initialState;
        }
    }
}